package yunjiao.javatutorials.guava.concurrent.comprehensive;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;

/**
 * 生产环境配置
 *
 * @author yangyunjiao
 */
@Slf4j
public class ProductionComprehensiveCondition extends ComprehensiveCondition {
    private final String conditionName;
    private final AtomicLong lastResetTime = new AtomicLong(System.currentTimeMillis());

    public ProductionComprehensiveCondition(Condition delegate, String conditionName) {
        super(delegate);
        this.conditionName = conditionName;
    }

    @Override
    public void await() throws InterruptedException {
        if (log.isDebugEnabled()) {
            log.debug("{} - 开始等待", conditionName);
        }

        long startTime = System.nanoTime();
        try {
            super.await();
        } catch (InterruptedException e) {
            log.warn("{} - 等待被中断", conditionName);
            throw e;
        } finally {
            long duration = System.nanoTime() - startTime;
            if (duration > 1_000_000_000L) { // 超过1秒的记录警告
                log.warn("{} - 长时间等待: {} ms", conditionName, duration / 1_000_000);
            }
        }
    }

    // 定时重置统计（避免长期运行内存占用）
    public void resetIfNeeded(long resetIntervalMs) {
        long currentTime = System.currentTimeMillis();
        long lastReset = lastResetTime.get();

        if (currentTime - lastReset > resetIntervalMs &&
                lastResetTime.compareAndSet(lastReset, currentTime)) {
            resetStatistics();
            log.info("{} - 定时重置统计信息", conditionName);
        }
    }

    // 生成监控指标（适合接入监控系统）
    public Map<String, Number> getMonitoringMetrics() {
        Map<String, Number> metrics = new HashMap<>();
        metrics.put(conditionName + ".waitCount", getWaitCount());
        metrics.put(conditionName + ".signalCount", getSignalCount());
        metrics.put(conditionName + ".signalAllCount", getSignalAllCount());
        metrics.put(conditionName + ".timeoutCount", getTimeoutCount());
        metrics.put(conditionName + ".interruptCount", getInterruptCount());
        metrics.put(conditionName + ".averageWaitTime", getAverageWaitTime());
        metrics.put(conditionName + ".maxWaitTime", getMaxWaitTime());
        return metrics;
    }
}
